# -*- coding: utf-8 -*-

"""
@Datetime: 2019/2/24
@Author: Zhang Yafei
"""
import json
import config
from urllib.request import quote
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import ElementNotVisibleException


class TicketGrabbing(object):
    """
    抢票系统
    """
    def __init__(self):
        self.get_station()
        self.wait_input()
        self.login_url = 'https://kyfw.12306.cn/otn/resources/login.html'
        self.initmy_url = 'https://kyfw.12306.cn/otn/view/index.html'
        self.search_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
        self.passenger_url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
        self.driver = webdriver.Chrome()
        self.station = None

    def get_station(self):
        with open('../station.txt', 'r') as f:
            self.station = json.loads(f.read())

    def wait_input(self):
        # self.from_station = '晋城'
        # self.to_station = '太原'
        # self.from_station_quote = quote(self.from_station)
        # self.to_station_quote = quote(self.to_station)
        # self.from_station_code = self.station[self.from_station]
        # self.to_station_code = self.station[self.to_station]
        # self.date = '2019-03-01'
        # self.passengers = ['张亚飞']
        # self.trains = ['K904']
        self.from_station = input('请输出出发地：')
        self.to_station = input('请输入目的地：')
        self.from_station_quote = quote(self.from_station)
        self.to_station_quote = quote(self.to_station)
        self.from_station_code = self.station[self.from_station]
        self.to_station_code = self.station[self.to_station]
        self.date = input('请输入日期(xxxx-xx-xx)：')
        self.passengers = input('乘客姓名（如有多个乘客，用英文逗号隔开）：').split(',')
        self.trains = input('车次（如有多个车次，用英文逗号隔开）：').split(',')

    def _login(self):
        self.driver.get(self.login_url)
        self.driver.find_element_by_css_selector('.login-hd-account a').click()
        self.driver.find_element_by_css_selector('.login-account #J-userName').send_keys(config.username)
        self.driver.find_element_by_css_selector('.login-account #J-password').send_keys(config.password)
        # 显示等待
        # 隐示等待
        WebDriverWait(self.driver, 1000).until(EC.url_to_be(self.initmy_url))
        print('登录成功')

    def _order_ticket(self):
        """
        预定车票方式一
        :return:
        """
        # 1. 跳转到查余票的页面
        self.query_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs={0},{1}&ts={2},{3}&date={4}&flag=N,N,Y'\
            .format(self.from_station_quote, self.from_station_code, self.to_station_quote, self.to_station_code, self.date)
        self.driver.get(self.query_url)

        # 2. 找到所有没有datatrain属性的tr标签，这些标签是存储了车次信息的
        tr_list = self.driver.find_elements_by_xpath(".//tbody[@id='queryLeftTable']/tr[not(@datatran)]")

        # 3. 遍历所有符合条件的tr标签
        for tr in tr_list:
            train_number = tr.find_element_by_class_name('number').text
            print(train_number)
            print('=' * 20)
            if train_number in self.trains:
                while True:
                    left_trcket = tr.find_element_by_xpath('.//td[4]').text
                    if left_trcket == '有' or left_trcket.isdigit:
                        tr.find_element_by_class_name('btn72').click()
                        # 4. 等待是否来到了确认来到了乘客信息的界面
                        WebDriverWait(self.driver, 1000).until(
                            EC.url_to_be(self.passenger_url)
                        )
                        # 5. 等待所有乘客信息是否被加载进来了
                        WebDriverWait(self.driver, 1000).until(
                            EC.presence_of_all_elements_located((By.XPATH, ".//ul[@id='normal_passenger_id']/li"))
                        )
                        # 6. 获取所有的乘客信息
                        passenger_labels = self.driver.find_elements_by_xpath(".//ul[@id='normal_passenger_id']/li/label")
                        for passenger_label in passenger_labels:
                            name = passenger_label.text.split('(')[0]
                            if name in self.passengers:
                                passenger_label.click()
                                if '学生' in passenger_label.text:
                                    WebDriverWait(self.driver, 1000).until(
                                        EC.presence_of_element_located((By.ID, 'dialog_xsertcj_ok'))
                                    )
                                    ok_btn = self.driver.find_element_by_id('dialog_xsertcj_ok')
                                    ok_btn.click()
                        # 7. 获取提交订单的按钮
                        self.driver.find_element_by_id('submitOrder_id').click()
                        # 8. 显示等待确认订单的对话框是否已经出现
                        WebDriverWait(self.driver, 1000).until(
                            EC.presence_of_element_located((By.CLASS_NAME, 'dhtmlx_wins_body_outer'))
                        )
                        # 9. 再来一个显示等待， 如果确认按钮出现了，那么就去执行点击操作
                        WebDriverWait(self.driver, 1000).until(
                            EC.presence_of_element_located((By.ID, 'qr_submit_id'))
                        )
                        confirm_btn = self.driver.find_element_by_id('qr_submit_id')
                        while confirm_btn:
                            # 循环执行确认订单按钮
                            try:
                                confirm_btn.click()
                                confirm_btn = self.driver.find_element_by_id('qr_submit_id')
                            except ElementNotVisibleException as e:
                                break

                        break

    def _order_tocket1(self):
        """
        预定车票方式二
        :return:
        """
        # 1. 跳转到查余票的页面
        self.driver.get(self.search_url)
        js1 = "document.getElementById('fromStation').setAttribute('type', 'text')"
        js2 = "document.getElementById('toStation').setAttribute('type', 'text')"
        js3 = "document.getElementById('train_date').removeAttribute('readonly')"

        self.driver.execute_script(js1)
        self.driver.execute_script(js2)
        self.driver.execute_script(js3)

        self.driver.implicitly_wait(5)

        self.driver.find_element_by_id('fromStation').send_keys(self.from_station_code)
        self.driver.find_element_by_id('toStation').send_keys(self.to_station_code)
        self.driver.find_element_by_id('train_date').clear()
        self.driver.find_element_by_id('train_date').send_keys(self.date)

        # 2. 如果能够被点击了，那么就找到这个查询按钮，执行点击事件
        self.driver.find_element_by_id('query_ticket').click()

        # 3. 在点击查询按钮以后，等待车次信息是否显示出来了
        WebDriverWait(self.driver, 1000).until(
            EC.presence_of_element_located((By.XPATH, ".//tbody[@id='queryLeftTable']/tr"))
        )

        # 4. 找到所有没有datatrain属性的tr标签，这些标签是存储了车次信息的
        tr_list = self.driver.find_elements_by_xpath(".//tbody[@id='queryLeftTable']/tr[not(@datatran)]")

        # 5. 遍历所有符合条件的tr标签
        for tr in tr_list:
            train_number = tr.find_element_by_class_name('number').text
            print(train_number)
            print('='*20)
            if train_number in self.trains:
                while True:
                    left_trcket = tr.find_element_by_xpath('.//td[4]').text
                    if left_trcket == '有' or left_trcket.isdigit:
                        tr.find_element_by_class_name('btn72').click()
                        # 6. 等待是否来到了确认来到了乘客信息的界面
                        WebDriverWait(self.driver, 1000).until(
                            EC.url_to_be(self.passenger_url)
                        )
                        # 7. 等待所有乘客信息是否被加载进来了
                        WebDriverWait(self.driver, 1000).until(
                            EC.presence_of_all_elements_located((By.XPATH, ".//ul[@id='normal_passenger_id']/li"))
                        )
                        # 8. 获取所有的乘客信息
                        passenger_labels = self.driver.find_elements_by_xpath(".//ul[@id='normal_passenger_id']/li/label")
                        for passenger_label in passenger_labels:
                            name = passenger_label.text.split('(')[0]
                            if name in self.passengers:
                                passenger_label.click()
                                if '学生' in passenger_label.text:
                                    WebDriverWait(self.driver, 1000).until(
                                        EC.presence_of_element_located((By.ID, 'dialog_xsertcj_ok'))
                                    )
                                    ok_btn = self.driver.find_element_by_id('dialog_xsertcj_ok')
                                    ok_btn.click()
                        # 8. 获取提交订单的按钮
                        self.driver.find_element_by_id('submitOrder_id').click()
                        self.driver.implicitly_wait(5)
                        ok_btn = self.driver.find_element_by_id('dialog_xsertcj_ok')
                        if ok_btn:
                            ok_btn.click()
                        # 9. 显示等待确认订单的对话框是否已经出现
                        WebDriverWait(self.driver, 1000).until(
                            EC.presence_of_element_located((By.CLASS_NAME, 'dhtmlx_wins_body_outer'))
                        )
                        # 10. 再来一个显示等待， 如果确认按钮出现了，那么就去执行点击操作
                        WebDriverWait(self.driver, 1000).until(
                            EC.presence_of_element_located((By.ID, 'qr_submit_id'))
                        )
                        confirm_btn = self.driver.find_element_by_class_name('qr_submit_id')
                        while confirm_btn:
                            # 循环执行确认订单按钮
                            try:
                                confirm_btn.click()
                                confirm_btn = self.driver.find_element_by_id('qr_submit_id')
                            except ElementNotVisibleException as e:
                                break

                        break

    def run(self):
        self._login()
        self._order_ticket()
        # self._order_tocket1()


if __name__ == '__main__':
    spider = TicketGrabbing()
    spider.run()